{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "代码裤子：<a href=\"https://github.com/lotapp/BaseCode\" target=\"_blank\">https://github.com/lotapp/BaseCode</a>\n",
    "\n",
    "在线编程：<a href=\"https://mybinder.org/v2/gh/lotapp/BaseCode/master\" target=\"_blank\">https://mybinder.org/v2/gh/lotapp/BaseCode/master</a>\n",
    "\n",
    "在线预览：<a href=\"http://github.lesschina.com/python/base/module/模块专题.html\" target=\"_blank\">http://github.lesschina.com/python/base/module/模块专题.html</a>\n",
    "\n",
    "老师休假度蜜月去了，这学期也到了尾声，小明同学觉得自己学的挺好的，在四处逛游的过程中看见了小潘的电脑，然后惊到了！"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n",
      "[3, 5, 7, 9, 11, 13, 15, 17, 19, 21]\n"
     ]
    }
   ],
   "source": [
    "# 导入matplotlib的pyplot模块\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "x_list=list(range(1,11))\n",
    "y_list=[y*2+1 for y in x_list]\n",
    "\n",
    "print(x_list)\n",
    "print(y_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 画图\n",
    "plt.plot(x_list,y_list)\n",
    "# 设置X，Y的坐标区间（可以不设置，用默认显示方式）\n",
    "plt.axis([0,10,0,25])\n",
    "# 显示图片\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "小潘昨晚螃蟹吃多了，今天拉肚子拉的不要不要的，现在去药店买紫苏和干姜来解蟹毒呢\n",
    "\n",
    "怎么办呢，感觉自己不再萌萌哒了，好心情瞬间被比下去了，小明内心不断思索中....\n",
    "\n",
    "作为一个吃胖了的小明，过了一分钟就调节好了，然后好好看小潘的Code\n",
    "\n",
    "咦，第一句是啥？不管，继续看`x_list=list(range(1,11))` `y_list=[y*2+1 for y in x_list]`\n",
    "\n",
    "这不是之前老师讲的<a href=\"https://www.cnblogs.com/dotnetcrazy/p/9155310.html#1.9.列表生成式\" target=\"_blank\">列表生成式</a>吗？然后就是画图了，好像也不是很难，开头到底是个啥，有了这个就可以几句话实现牛逼哄哄的技能了，不行得买瓶饮料问问课代表伟哥～\n",
    "\n",
    "一进伟哥宿舍就发现，伟哥在给舍友们补课？这是要讲课的节奏吗？赶紧凑过来学习～\n",
    "\n",
    "## 1.模块导入\n",
    "\n",
    "模块就是一组功能的集合体，我们的程序可以导入模块来复用模块里的功能\n",
    " \n",
    "在Python中，一个py文件就称之为一个 **模块**（Module）\n",
    "\n",
    "我们先来讲讲 **模块怎么导入**，上学期我们学了点C，发现每个文件开头都有一个`#include <stdio.h>`\n",
    "\n",
    "这个就类似我们说的模块导入了，咱们Python的模块导入和Java有点像用 `import` 来导入\n",
    "\n",
    "先看个例子 ～ 我们定义了一个test.py文件，里面定义了这么一个函数：\n",
    "\n",
    "```py\n",
    "# %load test.py\n",
    "def show():\n",
    "    print(\"---show---\")\n",
    "```\n",
    "\n",
    "我们想在新的py文件中使用这个函数\n",
    "\n",
    "### 1.1.import导入方式1\n",
    "\n",
    "`import test` 把这个文件直接导入进来了\n",
    "\n",
    "```py\n",
    "import test\n",
    "\n",
    "test.show()\n",
    "```\n",
    "执行结果：\n",
    "```\n",
    "---show---\n",
    "```\n",
    "\n",
    "### 1.2.from…import导入方式2\n",
    "\n",
    "有时候我们只需要用到模块中的某个函数，只需要引入该函数即可\n",
    "\n",
    "`from test import show` 把这个文件的show方法导入进来，调用的时候直接`show()`即可\n",
    "\n",
    "```py\n",
    "from test import show\n",
    "\n",
    "show()\n",
    "```\n",
    "执行结果：\n",
    "```\n",
    "---show---\n",
    "```\n",
    "\n",
    "**使用模块有什么好处？**\n",
    "\n",
    "1. **提高了代码的维护性**，当一个模块编写完毕，就可以被其他地方引用。\n",
    "\n",
    "2. 使用模块还可以 **避免函数名和变量名冲突**。相同名字的函数和变量完全可以分别存在不同的模块中\n",
    "\n",
    "我们自己在编写模块时，不必考虑名字会与其他模块冲突(不要和<a href=\"https://docs.python.org/3/library/functions.html\" blank=\"_self\">内置函数</a>名字冲突)\n",
    "\n",
    "![图片](https://images2018.cnblogs.com/blog/1127869/201807/1127869-20180702113751695-1093910460.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.3.导入多个模块\n",
    "\n",
    "看着小明一愣一愣的，加上那瓶菊花茶的面子，课代表来了一个demo：\n",
    "\n",
    "test1.py\n",
    "```py\n",
    "test_str = \"111\"\n",
    "\n",
    "def show():\n",
    "    print(__name__, \"show\")\n",
    "\n",
    "```\n",
    "test2.py\n",
    "```py\n",
    "test_str = \"222\"\n",
    "\n",
    "def show():\n",
    "    print(__name__, \"show\")\n",
    "\n",
    "```\n",
    "\n",
    "可以以`,`分隔（**这种导入方式，官方推荐多行导入**）\n",
    "```py\n",
    "import test1, test2\n",
    "\n",
    "print(test1.test_str)\n",
    "\n",
    "print(test2.test_str)\n",
    "\n",
    "test1.show()\n",
    "\n",
    "test2.show()\n",
    "```\n",
    "结果：\n",
    "```\n",
    "111\n",
    "222\n",
    "test1 show\n",
    "test2 show\n",
    "```\n",
    "\n",
    "还可以用这种方式，该模块里面的函数名、变量名以逗号分隔（不用多行）\n",
    "\n",
    "通过这种方式引入的时候，是当两个模块中含有相同名称函数的时候，后面一次引入会覆盖前一次引入，所以用`as`来避免一下\n",
    "\n",
    "```py\n",
    "from test1 import show as show1, test_str as test_str1\n",
    "from test2 import show as show2, test_str as test_str2\n",
    "\n",
    "print(test_str1)\n",
    "print(test_str2)\n",
    "\n",
    "show1()\n",
    "show2()\n",
    "```\n",
    "结果：\n",
    "```\n",
    "111\n",
    "222\n",
    "test1 show\n",
    "test2 show\n",
    "```\n",
    "如果想引入模块中所有东西可以用 **`from 模块名 import *`**，这样所有**被允许**(过会讲)的变量和函数都被导入进来了(**少用**)\n",
    "\n",
    "`from 模块名 import` 好处：使用起来方便了，坏处：容易与当前执行文件中的名字冲突"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.模块的简单自测试\n",
    "\n",
    "小明恍然大悟，盯着`__name__`看了好久，然后结合前面的知识，乘着旁边位置电脑没人，写了一半的demo卡壳了：\n",
    "\n",
    "get_infos.py\n",
    "```py\n",
    "def get_infos():\n",
    "    print(\"信息如下：xxxx\")\n",
    "\n",
    "def main():\n",
    "    get_infos()\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()\n",
    "```\n",
    "\n",
    "伟哥过来瞟了一眼继续讲到：\n",
    "\n",
    "之前老师讲面向对象的时候有提到标准格式写法：\n",
    "```py\n",
    "def main():\n",
    "    get_infos()\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()\n",
    "```\n",
    "python文件可以有两种用途：\n",
    "\n",
    "1. 当做 **脚本**来单独使用或者执行\n",
    "2. 当做 **模块**来给别人调用\n",
    "\n",
    "那怎么区分呢？就要用到`__name__`了\n",
    "\n",
    "我们来看个案例就懂了：\n",
    "\n",
    "get_user_infos.py\n",
    "```py\n",
    "def get_infos():\n",
    "    print(__name__)\n",
    "    print(\"信息如下：xxxx\")\n",
    "\n",
    "def main():\n",
    "    get_infos()\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()\n",
    "```\n",
    "再定义一个函数来调用它\n",
    "```py\n",
    "import get_user_infos as user_infos\n",
    "\n",
    "user_infos.get_infos()\n",
    "```\n",
    "\n",
    "**直接执行的时候`__name__`等于`__main__`，别人调用的时候显示该文件名**\n",
    "![图片](https://images2018.cnblogs.com/blog/1127869/201807/1127869-20180702152444802-1155759925.png)\n",
    "\n",
    "\n",
    "这样的好处就是==> 避免被别人导入的时候执行某些Code\n",
    "\n",
    "小明乐坏了，平时和小潘以前做项目老被吐槽，学了这个得好好嘲讽一下小潘了\n",
    "\n",
    "以后再也不怕直接py文件各种问题了，咱们可以先简单自测一下O(∩_∩)O哈！"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3.控制可使用的函数、变量、类\n",
    "\n",
    "### 3.1.通过私有来控制\n",
    "\n",
    "在一个模块中，我们可能会定义很多函数和变量，但有的函数和变量我们希望给别人使用，有的函数和变量我们希望仅仅在模块内部使用。在Python中，是通过`_`前缀来实现的\n",
    "\n",
    "小明同学基础功底扎实，看见标题小明就乐了，前面看了这么多案例瞬间秒懂，大叫道～”等一下～～～我来写demo，要是不行请你们吃晚饭～“\n",
    "\n",
    "写下了如下代码：\n",
    "\n",
    "test3.py\n",
    "```py\n",
    "def test1():\n",
    "    print(\"test1\")\n",
    "\n",
    "\n",
    "def _test2():\n",
    "    print(\"test2\")\n",
    "\n",
    "\n",
    "def __test3():\n",
    "    print(\"test3\")\n",
    "```\n",
    "调用代码：\n",
    "```py\n",
    "import test3\n",
    "\n",
    "test3.test1()\n",
    "test3._test2()\n",
    "test3.__test3()\n",
    "```\n",
    "结果：\n",
    "```\n",
    "test1\n",
    "test2\n",
    "test3\n",
    "```\n",
    "大家大眼瞪小眼的看着小明，嘴角边露出了阴谋的味道～\n",
    "\n",
    "这下小明傻眼了，难道老师之前类的私有系列讲错了？\n",
    "\n",
    "小平瞥了小明一眼说道，你自己的打开方式不对还怪老师咯？看我给你改改~\n",
    "\n",
    "调用代码：\n",
    "```py\n",
    "from test3 import *\n",
    "\n",
    "test1()\n",
    "_test2()\n",
    "__test3()\n",
    "```\n",
    "小明运行后就傻眼了，心想到，课代表这个宿舍卧虎藏龙啊，下次少来点，不然这点老底就被他们吃空了\n",
    "\n",
    "`NameError: name '_test2' is not defined`\n",
    "\n",
    "注释掉`_test2()`运行结果：\n",
    "`NameError: name '__test3' is not defined`\n",
    "\n",
    "小明有点尴尬，然后转了个话题，说道：”那import不是无敌了？我们的私有不给力啊？“\n",
    "\n",
    "伟哥语重心长的说道：\n",
    "\n",
    "类似`_xxx`和`__xxx`这样的函数或变量就是非公开的（private），不应该被直接引用\n",
    "\n",
    "之所以我们说，“不应该”被直接引用，而不是“不能”被直接引用，是因为Python并没有一种方法可以完全限制访问private函数或变量\n",
    "\n",
    "比如小明的那种方式就可以直接使用了，但是从编程习惯上不应该引用private函数或变量。\n",
    "\n",
    "我们平时使用的时候：\n",
    "\n",
    "**外部不需要引用的函数全部定义成private，只有外部需要引用的函数才定义为public**,然后导入的时候尽量使用**`from ... import`**\n",
    "\n",
    "### 3.2.通过\\__all\\__来控制\n",
    "\n",
    "来个案例即可：\n",
    "\n",
    "test4.py\n",
    "```py\n",
    "__all__ = [\"Dog\", \"test1\", \"name\"]\n",
    "\n",
    "class Animal(object):\n",
    "    pass\n",
    "\n",
    "class Dog(Animal):\n",
    "    pass\n",
    "\n",
    "class Cat(Animal):\n",
    "    pass\n",
    "\n",
    "def test1():\n",
    "    print(\"test1\")\n",
    "\n",
    "def test2():\n",
    "    print(\"test2\")\n",
    "\n",
    "def test3():\n",
    "    print(\"test3\")\n",
    "\n",
    "name = \"小明\"\n",
    "age = \"22\"\n",
    "```\n",
    "效果：只有`__all__`列表里面的才能被访问\n",
    "![图片](https://images2018.cnblogs.com/blog/1127869/201807/1127869-20180702170300780-117831880.png)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4.二进制文件pyc\n",
    "\n",
    "小明，看到使用的电脑出现了这么多的pyc文件，以为中毒了，慌了慌了，连忙问道：\"伟哥伟哥，这个pyc是啥啊？不会是病毒吧？\"\n",
    "```\n",
    "├── 1.def_module.py\n",
    "├── 2.use_module.py\n",
    "├── 3.use_name.py\n",
    "├── 4.use_module.py\n",
    "├── 5.use_all_.py\n",
    "├── get_user_infos.py\n",
    "├── __pycache__\n",
    "│   ├── get_user_infos.cpython-36.pyc\n",
    "│   ├── test1.cpython-36.pyc\n",
    "│   ├── test2.cpython-36.pyc\n",
    "│   ├── test3.cpython-36.pyc\n",
    "│   ├── test4.cpython-36.pyc\n",
    "│   └── test.cpython-36.pyc\n",
    "├── test1.py\n",
    "├── test2.py\n",
    "├── test3.py\n",
    "├── test4.py\n",
    "└── test.py\n",
    "\n",
    "```\n",
    "旁边小李嘲笑道～”这你都不知道“\n",
    "\n",
    "为了 **提高加载模块的速度**，python解释器会在__pycache__目录中下缓存每个模块编译后的版本\n",
    "\n",
    "格式为：**`模块名.Python版本号.pyc`** 这种命名规范保证了编译后的结果多版本共存\n",
    "\n",
    "小明问道，那我更新文件它怎么办呢？\n",
    "\n",
    "小李瞥了一眼说道：\n",
    "\n",
    "Python检查源文件的修改时间与编译的版本进行对比，如果过期就自动重新编译\n",
    "\n",
    "并且编译的模块是平台独立的，所以相同的库可以在不同的架构的系统之间共享\n",
    "\n",
    "小明恍然大悟，说道：\n",
    "\n",
    "这不类似于Java和Net嘛，将来咋们编写的东西都可以跨平台了啊，O(∩_∩)O~，反正是由python虚拟机来执行的，太方便了\n",
    "\n",
    "PS：pyc文件是可以反编译的，因而它的出现仅仅是用来提升模块的加载速度的，不是用来加密的"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5.自己添加模块路径\n",
    "\n",
    "小明乘着大家休息的时候回宿舍拿了个笔记本，继续听道：\n",
    "\n",
    "当你导入一个模块，Python解析器对模块位置的搜索顺序是：\n",
    "\n",
    "1. 当前目录\n",
    "2. 如果不在当前目录，Python则搜索在shell变量PYTHONPATH下的每个目录。\n",
    "3. 如果都找不到，Python会查看默认路径。xinux下，默认路径一般为/usr/local/lib/python/\n",
    "4. 模块搜索路径存储在system模块的`sys.path`变量中。变量里包含当前目录，PYTHONPATH和由安装过程决定的默认目录\n",
    "\n",
    "**总之你看`sys.path`就对了**\n",
    "\n",
    "前几天时间发布了Python3.7，我们设置vscode的运行环境为Python3.7，然后看看：\n",
    "![图片](https://images2018.cnblogs.com/blog/1127869/201807/1127869-20180702172508241-1610564247.png)\n",
    "\n",
    "我用的是conda的一个路径,Python3.7相关的一下插件没那么完善，我用的是3.6系列，`3.7`你可以用来练习一下`新语法糖`\n",
    "![图片](https://images2018.cnblogs.com/blog/1127869/201807/1127869-20180702172517954-472710108.png)\n",
    "```\n",
    "['', # 当前目录\n",
    "'/usr/lib/python37.zip', '/usr/lib/python3.7', \n",
    "'/usr/lib/python3.7/lib-dynload',\n",
    " '/usr/local/lib/python3.7/dist-packages', \n",
    " '/usr/lib/python3/dist-packages']\n",
    "```\n",
    "\n",
    "小明心想，我是省事直接装了个conda路径是啥呢？于是自己测试了下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['', '/home/dnt/anaconda3/lib/python36.zip', '/home/dnt/anaconda3/lib/python3.6', '/home/dnt/anaconda3/lib/python3.6/lib-dynload', '/home/dnt/.local/lib/python3.6/site-packages', '/home/dnt/anaconda3/lib/python3.6/site-packages', '/home/dnt/anaconda3/lib/python3.6/site-packages/IPython/extensions', '/home/dnt/.ipython']\n"
     ]
    }
   ],
   "source": [
    "# conda的默认搜索路径\n",
    "import sys\n",
    "\n",
    "print(sys.path)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "运维方面用些许，平时用的不是很多，一带而过~\n",
    "\n",
    "细心可以看到，sys.path是一个列表，那么你对其添加删除操作也是和list一样的\n",
    "\n",
    "比如这个场景，服务器给不同的用户使用，又不想他们的程序访问到超过其文件夹外的文件（系统、其他用户）\n",
    "\n",
    "那么可以弄一个公共的库文件夹（手段先不用管），用程序模拟一下\n",
    "![图片](https://images2018.cnblogs.com/blog/1127869/201807/1127869-20180702174925447-1487510141.png)\n",
    "\n",
    "**这种方法是在运行时修改，运行结束后失效**\n",
    "\n",
    "其实还可以设置环境变量`pythonpath`，该环境变量的内容会被自动添加到模块搜索路径中。设置方式与设置Path环境变量类似。\n",
    "\n",
    "注意只需要添加你自己的搜索路径，Python自己本身的搜索路径不受影响。（列表第二个就是说的这个）\n",
    "\n",
    "\n",
    "## 6.模块重新导入\n",
    "\n",
    "import语句是可以在程序中的任意位置使用的,且针对同一个模块很import多次\n",
    "\n",
    "为了防止你重复导入，python的优化手段是：\n",
    "\n",
    "**第一次导入后就将模块名加载到内存了，后续的import语句仅是对已经加载到内存中的模块对象增加了一次引用，不会重新执行模块内的语句**\n",
    "\n",
    "看个例子：\n",
    "![图片](https://images2018.cnblogs.com/blog/1127869/201807/1127869-20180703083434028-424268461.png)\n",
    "\n",
    "想要重新导入修改的模块，可以使用官方推荐的方法：`importlib`下面的`reload`方法\n",
    "\n",
    "```py\n",
    "from importlib import reload\n",
    "\n",
    "reload(test)\n",
    "```\n",
    "\n",
    "当然了你也可以使用`imp`下面的`reload`方法（<a href=\"https://docs.python.org/3/library/imp.html\" target=\"_blank\">3.4往后，官方就不推荐使用 **imp** 了</a>）\n",
    "\n",
    "### 6.1.循环导入的问题\n",
    "\n",
    "稍微提一下循环导入（类似于C#循环引用），能避免就避免。\n",
    "\n",
    "**子模块相对独立，尽量别相互导入，通过父模块来调用** (有点像微服务的感觉)\n",
    "\n",
    "这样不会混乱也不会出现循环导入的问题了\n",
    "\n",
    "如果项目里面真的出现了循环导入，那么可以这么解决（参考）：\n",
    "\n",
    "1. 重新设计架构，解除相互引用的关系\n",
    "2. 把import语句放置在模块的最后\n",
    "3. 把import语句放置在函数中"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7.常用模块\n",
    "\n",
    "看到标题小明就乐了，这不～终于可以说话了，不用被他们压抑的不敢出声了～\n",
    "\n",
    "之前说了很多，比如`time`,`random`,`sys`等等，这次再扩充几个用的比较多的模块\n",
    "\n",
    "后面demo里面还会再说，可以自己学习一下（<a href=\"https://docs.python.org/3/library\" target=\"_blank\">官方文档</a>）（<a href=\"https://github.com/python/cpython/tree/3.7/Lib\" target=\"_blank\">源码文件</a>）\n",
    "\n",
    "### 7.1.time and datetime\n",
    "\n",
    "在Python中，通常有这几种方式来表示时间：\n",
    "\n",
    "由于Python的**time**模块实现主要调用C库，所以各个平台可能有所不同\n",
    "\n",
    "1. 时间戳（timestamp）：从1970年1月1日00:00:00开始按秒计算的偏移量\n",
    "    - `type(time.time())` ==> `float`\n",
    "    - 返回时间戳方式的函数主要有`time()`，`clock()`(这个Win和Xinux系列有些区别)等\n",
    "2. 格式化的时间字符串\n",
    "3. UTC世界标准时间(在中国为UTC+8)，DST（Daylight Saving Time）即夏令时。\n",
    "    - 元组（struct_time）共有9个元素\n",
    "    - 返回struct_time的函数主要有gmtime()，localtime()，strptime()\n",
    "\n",
    "看到表格不用怀疑，没错，更详细可以看<a href=\"https://docs.python.org/3/library/time.html#time.struct_time\" target=\"_blank\">官方介绍</a>\n",
    "```\n",
    "| 索引　| 属性                    　| 值                        |\n",
    "| ---- | -------------------------| ------------------------- |\n",
    "| 0    | tm_year（年）             | eg:2018                   |\n",
    "| 1    | tm_mon（月）              | range [1, 12]             |\n",
    "| 2    | tm_mday（日）             | range [1, 31]             |\n",
    "| 3    | tm_hour（时）             | range [0, 23]             |\n",
    "| 4    | tm_min（分）              | range [0, 59]             |\n",
    "| 5    | tm_sec（秒）              | range [0, 61]             |\n",
    "| 6    | tm_wday（星期几）        　| range [0, 6]（0表示周日）   |\n",
    "| 7    | tm_yday（一年中的第几天）   | range [1, 366]            |\n",
    "| 8    | tm_isdst（是否是夏令时）  　| 0, 1 or -1                |\n",
    "```\n",
    "\n",
    "**`datetime`模块**\n",
    "\n",
    "`datetime.datetime.now().strftime(\"%Y-%m-%d %X\")`\n",
    "\n",
    "主要是时间相关的封装，案例在time模块的下面："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1530595914.981183\n",
      "2018-07-03 13:31:54\n",
      "time.struct_time(tm_year=2018, tm_mon=7, tm_mday=3, tm_hour=13, tm_min=31, tm_sec=54, tm_wday=1, tm_yday=184, tm_isdst=0)\n",
      "time.struct_time(tm_year=2018, tm_mon=7, tm_mday=3, tm_hour=5, tm_min=31, tm_sec=54, tm_wday=1, tm_yday=184, tm_isdst=0)\n",
      "1530595914.0\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "\n",
    "# 时间戳，结果是float类型\n",
    "print(time.time())\n",
    "\n",
    "# 格式化的时间字符串：年-月-日 小时:分钟:秒\n",
    "print(time.strftime(\"%Y-%m-%d %X\"))\n",
    "\n",
    "\n",
    "print(time.localtime())  # 本地时区的 struct_time\n",
    "print(time.gmtime())  # UTC时区（世界标准时间）的struct_time\n",
    "\n",
    "# time.mktime 将一个 struct_time 转化为时间戳\n",
    "print(time.mktime(time.localtime()))\n",
    "\n",
    "# t = time.localtime()\n",
    "# print(time.asctime(t)) # 把一个表示时间的元组或者struct_time表示为这种形式：'Sun Jun 20 23:21:05 1993'\n",
    "# print(time.asctime()) # 不写参数默认就是time.localtime()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2018-07-03 13:31:55.147268\n",
      "2018-07-03 13:31:55\n",
      "2018-07-06 13:31:55.147883\n",
      "2018-06-30 13:31:55.148109\n",
      "2018-07-03 16:31:55.148315\n",
      "2018-07-03 14:01:55.148532\n"
     ]
    }
   ],
   "source": [
    "import datetime\n",
    "\n",
    "print(datetime.datetime.now())  # 当前时间 2018-07-03 13:02:20.824494\n",
    "print(datetime.datetime.now().strftime(\"%Y-%m-%d %X\"))  # 当前时间 2018-07-03 13:02:20\n",
    "\n",
    "# 时间加减\n",
    "print(datetime.datetime.now() + datetime.timedelta(3))  # 当前时间+3天\n",
    "print(datetime.datetime.now() + datetime.timedelta(-3))  # 当前时间-3天\n",
    "print(datetime.datetime.now() + datetime.timedelta(hours=3))  # 当前时间+3小时\n",
    "print(datetime.datetime.now() + datetime.timedelta(minutes=30))  # 当前时间+30分"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7.2.random\n",
    "\n",
    "`random`小明有好好研究，于是抢着讲解：\n",
    "\n",
    "常用方法主要是这几个：\n",
    "\n",
    "`random.random()`：大于0且小于1之间的小数\n",
    "\n",
    "`random.randint(1, 3)`：[1,3] 大于等于1且小于等于3之间的整数\n",
    "\n",
    "`random.randrange(1, 3)`：[1,3) 大于等于1且小于3之间的整数\n",
    "\n",
    "`random.choice([4, 'a', [1, 2]])`：随机返回三者之一\n",
    "\n",
    "`random.uniform(1, 3)`：大于1小于3的小数，如1.927109612082716\n",
    "\n",
    "`random.sample(old_list, 5)`：从list中随机获取5个元素，作为一个片断返回\n",
    "\n",
    "`random.shuffle(old_list)`：打乱list的顺序\n",
    "\n",
    "下面来看看例子吧（最下面有个简单验证码的demo）:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import random"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.08269940155686328\n",
      "3\n",
      "2\n",
      "[1, 2]\n",
      "2.1607974783487136\n"
     ]
    }
   ],
   "source": [
    "print(random.random())  # 大于0且小于1之间的小数\n",
    "\n",
    "print(random.randint(1, 3))  # [1,3]    大于等于1且小于等于3之间的整数\n",
    "\n",
    "print(random.randrange(1, 3))  # [1,3)    大于等于1且小于3之间的整数\n",
    "\n",
    "print(random.choice([4, 'a', [1, 2]]))  # 随机返回三者之一\n",
    "\n",
    "print(random.uniform(1, 3))  # 大于1小于3的小数，如1.927109612082716"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n",
      "[7, 6, 9, 10, 3]\n"
     ]
    }
   ],
   "source": [
    "# 从list中随机获取N个元素，作为一个片断返回\n",
    "old_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n",
    "new_list = random.sample(old_list, 5)  # 从list中随机获取5个元素，作为一个片断返回\n",
    "print(old_list)\n",
    "print(new_list)  # 原有序列并没有改变"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 5, 7, 9, 3]\n"
     ]
    }
   ],
   "source": [
    "test_list = [1, 3, 5, 7, 9]\n",
    "random.shuffle(test_list)  # 打乱test_list的顺序\n",
    "print(test_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "KOOH\n"
     ]
    }
   ],
   "source": [
    "# 简单验证码的例子\n",
    "import random\n",
    "\n",
    "\n",
    "def get_code(n):\n",
    "    \"\"\"简单验证码\"\"\"\n",
    "    code = \"\"\n",
    "    for i in range(n):\n",
    "        s1 = chr(random.randint(65, 90))  # 字母\n",
    "        s2 = str(random.randint(0, 9))  # 数字\n",
    "        code += random.choice([s1, s2])  # 随机返回s1 or s2\n",
    "    return code\n",
    "\n",
    "\n",
    "def main():\n",
    "    print(get_code(4))\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    main()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7.3.hashlib\n",
    "\n",
    "一看到hashlib，小明就退缩了，只能继续听伟哥讲解：\n",
    "\n",
    "官方文档：<a href=\"https://docs.python.org/3/library/hashlib.html\" blank=\"_self\">https://docs.python.org/3/library/hashlib.html</a>\n",
    "\n",
    "简单hash：**`hashlib.sha256(pass_str.encode(\"utf-8\")).hexdigest()`**\n",
    "\n",
    "和key一起加密：\n",
    "```py\n",
    "import hashlib\n",
    "\n",
    "pass_str = \"123456\"\n",
    "\n",
    "m = hashlib.sha256()\n",
    "\n",
    "m.update(pass_str.encode(\"utf-8\"))\n",
    "\n",
    "m.update(\"你设置的key\".encode(\"utf-8\"))\n",
    "\n",
    "pass_str_new = m.hexdigest()\n",
    "```\n",
    "\n",
    "扩展：python 还有一个`hmac`模块，它内部对我们创建`key`和`pass`进行处理后再加密：<a href=\"https://docs.python.org/3/library/hmac.html\" blank=\"_self\">https://docs.python.org/3/library/hmac.html</a>\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "import hashlib\n",
    "\n",
    "pass_str = \"123456\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92\n",
      "64\n"
     ]
    }
   ],
   "source": [
    "# 简单hash一下\n",
    "m = hashlib.sha256()\n",
    "\n",
    "m.update(pass_str.encode(\"utf-8\"))\n",
    "\n",
    "pass_str_new = m.hexdigest()\n",
    "\n",
    "print(pass_str_new)\n",
    "print(len(pass_str_new))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92'"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 简写：\n",
    "hashlib.sha256(pass_str.encode(\"utf-8\")).hexdigest()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "fadc86f44ab0f13346bf3293b5bc51112569a21e421809f93a096c917d7731ce\n",
      "64\n"
     ]
    }
   ],
   "source": [
    "# 简写这么方便为什么要像上面例子那么复杂呢？\n",
    "# 直接加密的方式可以通过撞库破解，但你可以设置个key来加大难度\n",
    "# 大部分网站都是用平台key + 用户key（可以是用户创建时间或者id之类的不变信息）来加密的\n",
    "m = hashlib.sha256()\n",
    "\n",
    "m.update(pass_str.encode(\"utf-8\"))\n",
    "\n",
    "m.update(\"你设置的key\".encode(\"utf-8\"))\n",
    "\n",
    "pass_str_new = m.hexdigest()\n",
    "\n",
    "print(pass_str_new)\n",
    "print(len(pass_str_new))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "常用模块里面还有很多，就不一一介绍了，比如：`functools`里面的偏函数`partial`\n",
    "\n",
    "这个我们下次讲闭包相关知识会说的`functools.partial(函数名, 默认参数1，默认参数2...)`\n",
    "\n",
    "\n",
    "## 8.第三方模块安装\n",
    "\n",
    "第三方模块安装之前有说过：<a href=\"https://www.cnblogs.com/dotnetcrazy/p/9095793.html\" target=\"_blank\">https://www.cnblogs.com/dotnetcrazy/p/9095793.html</a>\n",
    "\n",
    "简单提一下：（<a href=\"https://pypi.org\" target=\"_blank\">pip官网</a>）\n",
    "\n",
    "```shell\n",
    "pip install 模块名 # 正常\n",
    "\n",
    "sudo pip install 模块名 # 没权限运行\n",
    "\n",
    "pip install --user 模块名 # conda下的pip\n",
    "```\n",
    "如果不想让包破坏自己的环境，可以使用：virtualenv，你可以作为扩展了解下（<a href=\"http://www.cnblogs.com/zhaof/p/8358902.html\" target=\"_blank\">参考</a>）\n",
    "\n",
    "---\n",
    "\n",
    "## 9.包系列（导入、发布、安装）\n",
    "\n",
    "如果不同的人编写的模块名相同怎么办？\n",
    "\n",
    "小明抢答曰：”为了避免模块名冲突，Python又引入了按目录来组织模块的方法，称为包（Package）“\n",
    "\n",
    "小张斜了一眼小明补充道：”相互间有联系功能的模块可以放在一个包里，这个包就有点像C#的文件夹和类库的概念了“\n",
    "\n",
    "小明不服气的把小潘那段代码的开头贴了出来：`import matplotlib.pyplot as plt`，然后叫嚣道：”怎么样，这个肯定用到了包“\n",
    "\n",
    "### 9.1.包的定义\n",
    "\n",
    "课代表看着这两个活宝，然后继续讲解道：\n",
    "\n",
    "**模块是一组Python代码的集合，可以使用其他模块，也可以被其他模块使用**\n",
    "\n",
    "比如一个模块的名称是`A.B`， 那么他表示一个包`A`中的子模块`B`\n",
    "\n",
    "刚说完，小明就得意的看着小张，然后继续听课：\n",
    "\n",
    "创建自己的模块时，要注意：\n",
    "\n",
    "1. 模块名要遵循Python变量命名规范，不要使用中文、特殊字符\n",
    "2. 模块名不要和系统模块名冲突（<a href=\"https://docs.python.org/3/library/index.html\" target=\"_blank\">标准库</a>）\n",
    "\n",
    "\n",
    "下面我们来一个简单的案例：\n",
    "\n",
    "自己定义一个包，目录结构如下：（`__init__.py`是空文件）\n",
    "```\n",
    "web/\n",
    "├── data.py\n",
    "├── __init__.py\n",
    "└── json.py\n",
    "```\n",
    "调用web包里面的`get_json()`方法：\n",
    "```py\n",
    "from web.json import get_json\n",
    "\n",
    "get_json()\n",
    "```\n",
    "或者：\n",
    "```py\n",
    "import web.json as json\n",
    "\n",
    "json.get_json()\n",
    "```\n",
    "\n",
    "**每一个包目录下面都会有一个`__init__.py`的文件，这个文件是必须存在的，否则Python就把这个目录当成普通目录**\n",
    "\n",
    "`__init__.py`可以是空文件，编译器默认会把它认成名字是文件夹名的**模块**，eg:`web`\n",
    "\n",
    "\n",
    "### 9.2.包的制定化 ～ 控制可使用的模块\n",
    "\n",
    "还记得之前讲得`__all__`吧，如果你想控制包里面的模块能否被访问使用，可以使用它\n",
    "\n",
    "比如web包下的__init__文件中写下这一句：**`__all__ = [\"json\"]`**\n",
    "\n",
    "神奇的事情发生了：\n",
    "```py\n",
    "from web import *\n",
    "\n",
    "json.get_json()\n",
    "\n",
    "data.get_data()\n",
    "```\n",
    "在调用`data.get_data()`的时候出现了如下错误：\n",
    "```\n",
    "NameError: name 'data' is not defined\n",
    "```\n",
    "\n",
    "小明想到了自己当时的那顿饭，然后用当时的思路试了下：\n",
    "```py\n",
    "# 你这样调就不行了\n",
    "import web\n",
    "\n",
    "web.data.get_data()\n",
    "```\n",
    "发现和上面一样的错误，然后夸张的说道～“哈哈哈，这种方式无敌了，里面有谁能调`data模块`下的`get_data()方法`我就请他喝饮料！”\n",
    "\n",
    "话刚落完，发现大家刷刷的提交了相同的代码：\n",
    "```py\n",
    "# 同样的，你硬是要调，python也拿你没办法\n",
    "import web.data as data\n",
    "\n",
    "data.get_data()\n",
    "```\n",
    "小明顿时崩溃了，自我安慰到：“反正都是要请你们吃晚饭的了，也不差这饮料了...”"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 9.3.发布一个包\n",
    "\n",
    "把我们之前的Code做一个包，目录结构如下：\n",
    "```\n",
    "├── datalib\n",
    "│   ├── base\n",
    "│   │   ├── get_user_infos.py\n",
    "│   │   ├── __init__.py\n",
    "│   │   ├── test1.py\n",
    "│   │   ├── test2.py\n",
    "│   │   ├── test3.py\n",
    "│   │   ├── test4.py\n",
    "│   │   └── test.py\n",
    "│   ├── __init__.py\n",
    "│   ├── main.py\n",
    "│   └── web\n",
    "│       ├── data.py\n",
    "│       ├── __init__.py\n",
    "│       └── json.py\n",
    "└── setup.py\n",
    "```\n",
    "模块的目录结构中包含一个setup.py文件，用于定义模块名称、包含的模块等模块信息\n",
    "\n",
    "固定格式如下：\n",
    "```py\n",
    "setup(name=\"模块名称\", version=\"版本\", description=\"模块描述\", author=\"模块作者\", py_modules=[包含的模块内容])\n",
    "```\n",
    "以demo为例：\n",
    "```py\n",
    "from distutils.core import setup\n",
    "\n",
    "setup(\n",
    "    name=\"datalib\",\n",
    "    version=\"1.0\",\n",
    "    description=\"数据相关的模块\",\n",
    "    author=\"小明\",\n",
    "    py_modules=[\n",
    "        \"datalib.base.get_user_infos\", \"datalib.base.test\", \"datalib.web.json\"\n",
    "    ])\n",
    "```\n",
    "build命令（构建模块）：`python setup.py sdist` 来张图更形象：\n",
    "\n",
    "![图片](https://images2018.cnblogs.com/blog/1127869/201807/1127869-20180703171932459-112491088.png)\n",
    "\n",
    "build文件夹：\n",
    "```\n",
    "dnt@MZY-PC:~/xiaoming/build$ tree\n",
    ".\n",
    "└── lib\n",
    "    └── datalib\n",
    "        ├── base\n",
    "        │   ├── get_user_infos.py\n",
    "        │   ├── __init__.py\n",
    "        │   └── test.py\n",
    "        └── web\n",
    "            ├── __init__.py\n",
    "            └── json.py\n",
    "\n",
    "```\n",
    "生成发布压缩包：**`python3 setup.py sdist`** 他会帮你打包成一个`tar.gz`的压缩包\n",
    "\n",
    "其实你不构建，直接sdist也是可以的\n",
    "\n",
    "```\n",
    "dnt@MZY-PC:~/xiaoming$ tree\n",
    ".\n",
    "├── datalib\n",
    "│   ├── base\n",
    "│   │   ├── get_user_infos.py\n",
    "│   │   ├── __init__.py\n",
    "│   │   ├── test1.py\n",
    "│   │   ├── test2.py\n",
    "│   │   ├── test3.py\n",
    "│   │   ├── test4.py\n",
    "│   │   └── test.py\n",
    "│   ├── __init__.py\n",
    "│   ├── main.py\n",
    "│   └── web\n",
    "│       ├── data.py\n",
    "│       ├── __init__.py\n",
    "│       └── json.py\n",
    "├── dist\n",
    "│   └── datalib-1.0.tar.gz\n",
    "├── MANIFEST\n",
    "└── setup.py\n",
    "```\n",
    "\n",
    "### 9.4.安装自己打包的模块\n",
    "\n",
    "安装比较简单，如果是build文件夹，直接`sudo python setup.py install`\n",
    "\n",
    "如果是tar.gz，那么解压后再执行`sudo python setup.py install`\n",
    "\n",
    "当然了，也可以目录安装：`python setup.py install --prefix=路径`\n",
    "\n",
    "查看包内容：`tar -tvf datalib-1.0.tar.gz`\n",
    "\n",
    "解包：`tar -zxvf datalib-1.0.tar.gz`\n",
    "\n",
    "这些基础命令如果还不是很熟悉的话，可以看看逆天2015年写的<a href=\"https://www.cnblogs.com/dunitian/p/4822807.html\" target=\"_blank\">LinuxBase</a>文档\n",
    "\n",
    "其实说句心里话，2015开始摸索虚拟机中的Linux，几年提升肯定是有的，但是绝对没有这几个月的Linux真机开发来得快\n",
    "\n",
    "逆天还是建议程序员尽快适应Linux环境开发，刚开始的确不方便，适应之后就感觉Win特别麻烦了...\n",
    "\n",
    "很多东西一个指令就可以实现的，重复执行的东西写个脚本批量执行\n",
    "\n",
    "当然了你Win下各种跑脚本也是一样的，但是别忘了～公司服务器基本上都是Linux的，该面对的总该来的，加油～"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## CSharp包相关知识\n",
    "\n",
    "Old C#相关的知识可以参考：<a href=\"https://www.cnblogs.com/dunitian/p/6015459.html\" target=\"_blank\">如何在nuget上传自己的包</a>\n",
    "\n",
    "NetCore可以用打包命令：`dotnet-pack`来打包成Nuget包，<a href=\"https://docs.microsoft.com/zh-cn/dotnet/core/tools/dotnet-pack\" target=\"_blank\">官方文档</a>说的很详细了，就不一一复述了\n",
    "\n",
    "打包当前目录中的项目：`dotnet pack`\n",
    "\n",
    "打包 app1 项目：`dotnet pack ~/projects/app1/project.csproj`\n",
    "\n",
    "打包当前目录中的项目并将生成的包放置到 nupkgs 文件夹：\n",
    "\n",
    "`dotnet pack --output nupkgs`\n",
    "\n",
    "将当前目录中的项目打包到 nupkgs 文件夹并跳过生成步骤：\n",
    "\n",
    "`dotnet pack --no-build --output nupkgs`\n",
    "\n",
    "使用 PackageVersion MSBuild 属性将包版本设置为 2.1.0：\n",
    "\n",
    "`dotnet pack /p:PackageVersion=2.1.0`\n",
    "\n",
    "打包特定目标框架的项目：\n",
    "\n",
    "`dotnet pack /p:TargetFrameworks=net45`\n",
    "\n",
    "打包项目，并使用特定运行时 (Windows 10) 进行还原操作（.NET Core SDK 2.0 及更高版本）：\n",
    "\n",
    "`dotnet pack --runtime win10-x64`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "小明听完了这节课，感叹道～ “模块用起来真是爽啊”\n",
    "\n",
    "然后问道：“为什么老师没讲呢？”\n",
    "\n",
    "其他人一起鄙视小明说道：“你自己睡大觉你自己心里没有点逼数吗？”\n",
    "\n",
    "小明大囧，感觉饮料和饭钱真是白花了。。。（完）"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
